package com.example.calculation;


import com.example.entity.CalRecipe;
import com.example.entity.Chef;
import com.example.entity.Equip;
import com.example.entity.GlobalDate;
import com.example.utils.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 胡帅博
 * @date 2020/10/4 9:31
 */
final public class ChefEquipRecipeThread implements Callable<Integer>{

    int gaobao = 231000;

    // final boolean cheap=true;

    int[][] playEquips;
    TopResult[] topResults;
    TempCalCache tempCalCache;
    AtomicInteger max;
    CountDownLatch control;
    // 分段后 ，本线程负责部分 的开始位置
    private int start;
    // 负责部分的  结束位置 ，limit肯定不比start小
    private int limit;
    private int[][][] scoreCache;
    private Chef[] ownChefs;
    private CalRecipe[] ownRecipes;
    private Equip[] ownEquips;


    public ChefEquipRecipeThread(int[][] playEquips, TopResult[] topResults, AtomicInteger max, GlobalDate globalDate, CountDownLatch control, int start, int limit) {
        this.playEquips = playEquips;
        this.topResults = topResults;
        this.max = max;

        ownChefs = globalDate.ownChefs;
        ownEquips = globalDate.ownEquips;
        ownRecipes = globalDate.ownRecipes;
        tempCalCache = globalDate.tempCalCache;

        this.control = control;
        this.start = start;
        this.limit = limit;
        this.scoreCache = tempCalCache.scoreCache;
    }


    @Override
    public Integer call() {
        long starttime, endtime;
        starttime = System.currentTimeMillis();
        int cal;
        TopResult curTop;
        int[] recipes, chefs, equips;

        boolean updateend;
        for (int i = start; i < limit; i++) {
            curTop = topResults[i];
            recipes = curTop.recepeids;
            chefs = curTop.chefs;

            for (int i2 = 0; i2 < playEquips.length; i2++) {
                equips = playEquips[i2];
                cal = cacheSoore(chefs, equips, recipes);
                for (int oldInt; ; ) {
                    updateend = true;
                    oldInt = max.get();
                    if (oldInt < cal) {
                        updateend = max.compareAndSet(oldInt, cal);
                        printResult(chefs, equips, recipes, oldInt, cal);
                    }
                    else if (cal >= gaobao) {
                          printResult(chefs, equips, recipes,oldInt, cal);
                    }
                    if (updateend) {
                        break;
                    }
                }
            }
        }
        control.countDown();
        endtime = System.currentTimeMillis();
        System.out.println((limit - start) + "组菜谱厨师排列,全厨具用时:" + (endtime - starttime) + "ms");
        return 0;
    }


    final private int cacheSoore(int[] chefIndexs, int[] equipIndexs, int[] recipes) {
        int score = 0;
        int[] recipeScore;

        //第一个厨师
        recipeScore = scoreCache[chefIndexs[0]][equipIndexs[0]];
        score = recipeScore[recipes[0]] + recipeScore[recipes[1]] + recipeScore[recipes[2]];

        //第二个厨师
        recipeScore = scoreCache[chefIndexs[1]][equipIndexs[1]];
        score += (recipeScore[recipes[3]] + recipeScore[recipes[4]] + recipeScore[recipes[5]]);

        //第三个厨师
        recipeScore = scoreCache[chefIndexs[2]][equipIndexs[2]];
        score += (recipeScore[recipes[6]] + recipeScore[recipes[7]] + recipeScore[recipes[8]]);

        return score;
    }


    final void printResult(int[] chefIndexs, int[] equipIndexs, int[] recipes, int oldInt, int score) {

        StringBuilder stringBuilder = new StringBuilder(300);
        ArrayNode json = JSON.getObjectMapper().createArrayNode();
        for (int i = 0; i < 3; i++) {
            stringBuilder.delete(0, stringBuilder.length());
            ObjectNode jsonObject = JSON.getObjectMapper().createObjectNode();
            jsonObject.put("chefs", ownChefs[chefIndexs[i]].getName());
            jsonObject.put("equip", ownEquips[equipIndexs[i]].getName());
            stringBuilder.append('[');
            stringBuilder.append(ownRecipes[recipes[(i * 3) + 0]]).append(",");
            stringBuilder.append(ownRecipes[recipes[(i * 3) + 1]]).append(",");
            stringBuilder.append(ownRecipes[recipes[(i * 3) + 2]]).append(']');
            try {
                jsonObject.put("recipes", JSON.getObjectMapper().readValue(stringBuilder.toString(), ArrayNode.class));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            json.add(jsonObject);
        }


        if (ownEquips[equipIndexs[0]].getRarity() + ownEquips[equipIndexs[1]].getRarity() + ownEquips[equipIndexs[2]].getRarity() == 6) {
            System.out.println("经济实惠的最大值" + oldInt + "-->" + score + "\n" + json.toString());
        } else {
            System.out.println("最大值更新(需要三星厨具) " + oldInt + "-->" + score + "\n" + json.toString());
        }


//        System.out.println(Arrays.toString(chefIndexs));
//        System.out.println(Arrays.toString(equipIndexs));
//        System.out.println(Arrays.toString(recipes));
    }


}
